<?php
	
namespace app\api\controller\v1;

use app\api\libray\Auth;
use think\request;
use think\route\dispatch\Controller;

/**
 * 上传操作
 */
class Upload extends Controller
{
    /**
     * OSS key
     *
     * @var string
     */
    protected $accessKeyId;

    /**
     * OSS secret
     *
     * @var string
     */
    protected $accessKeySecret;

    /**
     * OSS endpoint
     *
     * @var string
     */
    protected $endpoint;

    /**
     * image bucket
     *
     * @var string
     */
    protected $imageBucket;

    /**
     * 图片回调地址
     *
     * @var string
     */
    protected $imageCallbackUrl;

    /**
     * 图片上传目录
     *
     * @var string
     */
    protected $imageUploadDir;

    /**
     * 图片大小最大限制,单位KB
     *
     * @var string
     */
    protected $imgaeMaxSize;

    /**
     * 初始化
     */
    protected function init()
    {
        // 基础信息
        $this->accessKeyId      = config('oss.accessKeyId');
        $this->accessKeySecret  = config('oss.accessKeySecret');
        $this->endpoint         = config('oss.endpoint');

        // 图片信息
        $this->imageBucket      = config('oss.imageBucket');
        $this->imageCallbackUrl = '回调地址，该demo地址为改文件中的：imageCallback()方法，请自己转成连接';
        $this->imageUploadDir   = 'images/'.$this->userInfo['app_id'].'/'.date('Ymd').'/';
        $this->imageMaxSize     = 1048576000;
    }

    /**
     * 获取图片签名
     */
    public function imageSign()
    {
        // 系统参数
        $callbackBody   = 'bucket=${bucket}&';
        $callbackBody  .= 'filename=${object}&';
        $callbackBody  .= 'etag=${etag}&';
        $callbackBody  .= 'size=${size}&';
        $callbackBody  .= 'mimeType=${mimeType}&';
        $callbackBody  .= 'height=${imageInfo.height}&';
        $callbackBody  .= 'width=${imageInfo.width}&';
        $callbackBody  .= 'format=${imageInfo.format}&';
        // 自定义参数
        $callbackBody  .= 'aaa=${x:aaa}&';
        $callbackBody  .= 'bbb=${x:bbb}&';

        $callback_param = [
            'callbackUrl'       => $this->imageCallbackUrl,
            'callbackBody'      => $callbackBody,
            'callbackBodyType'  => 'application/x-www-form-urlencoded',
        ];
        $callback_string = json_encode($callback_param);
        $base64_callback_body = base64_encode($callback_string);

        $now = time();
        $expire = 30; //设置该policy超时时间是30s. 即这个policy过了这个有效时间，将不能访问
        $end = $now + $expire;
        $expiration = $this->gmtIso8601($end);

        // 最大文件大小
        $condition = [
            0 => 'content-length-range',
            1 => 0,
            2 => $this->imageMaxSize,
        ];
        $conditions[] = $condition;

        // 表示用户上传的数据,必须是以$dir开始, 不然上传会失败
        $dir   = $this->imageUploadDir;
        $start = [
            0 => 'starts-with',
            1 => '$key',
            2 => $dir,
        ];
        $conditions[] = $start;

        $arr = [
            'expiration'    => $expiration,
            'conditions'    => $conditions
        ];
        $policy         = json_encode($arr);
        $base64_policy  = base64_encode($policy);
        $string_to_sign = $base64_policy;
        $signature      = base64_encode(hash_hmac('sha1', $string_to_sign, $this->accessKeySecret, true));

        // 构造返回参数
        $response['accessid']   = $this->accessKeyId;
        $response['host']       = $this->endpoint;
        $response['policy']     = $base64_policy;
        $response['signature']  = $signature;
        $response['expire']     = $end;
        $response['callback']   = $base64_callback_body;
        //这个参数是设置用户上传指定的前缀
        $response['dir'] = $dir;
        $data['oss'] = $response;
        $data['user_info']['app_id'] = $this->userInfo['app_id'];
        $data['user_info']['org_id'] = $this->userInfo['org_id'];
        $data['user_info']['uid']    = $this->userInfo['uid'];
        header('content-type:application/json');
        echo json_encode($data);die;
    }

    protected function gmtIso8601($time)
    {
        $dt_str = date("c", $time);
        $mydatetime = new \DateTime($dt_str);
        $expiration = $mydatetime->format(\DateTime::ISO8601);
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);
        return $expiration."Z";
    }

    /**
     * 图片上传OSS回调处理
     */
    public function imageCallback()
    {
        $authorizationBase64 = "";
            $pubKeyUrlBase64     = "";
            if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
                $authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION'];
            }

            if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL'])) {
                $pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL'];
            }

            if ($authorizationBase64 == '' || $pubKeyUrlBase64 == '') {
                header("http/1.1 403 Forbidden");
                exit();
            }

            // 2.获取OSS的签名
            $authorization = base64_decode($authorizationBase64);

            // 3.获取公钥
            $pubKeyUrl = base64_decode($pubKeyUrlBase64);
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $pubKeyUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
            $pubKey = curl_exec($ch);
            if ($pubKey == "") {
                header("http/1.1 403 Forbidden");
                exit();
            }

            // 4.获取回调body
            $body = file_get_contents('php://input');

            // 5.拼接待签名字符串
            $authStr = '';
            $path = $_SERVER['REQUEST_URI'];
            $pos = strpos($path, '?');
            if ($pos === false) {
                $authStr = urldecode($path)."\n".$body;
            } else {
                $authStr = urldecode(substr($path, 0, $pos)).substr($path, $pos, strlen($path) - $pos)."\n".$body;
            }

            // 6.验证签名
            $ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5);
            // 签名出错返回信息
            if ($ok != 1) {
                header("http/1.1 403 Forbidden");
                exit();
            }
            // 数据处理
            $this->paserData();

            header("Content-Type: application/json");

            $filename = $this->request->post('filename');
            $url = $this->endpoint . '/' . $filename;
            ob_clean();
            echo json_encode(array());die;
    }

    protected function paserData(){
        $param = $this->request->post();
        $param['filename'];
    }

    /**
     * 获取UUID值
     *     UUID含义是 通用唯一识别码 (Universally Unique Identifier)，这 是一个软件建构的标准
     * 
     * @param   stirng  [$prefix]  指定的前缀
     * 
     * @return  string  UUID值
     */
    protected function createUUID($prefix = ""){    //可以指定前缀
        $str = md5(uniqid(mt_rand(), true));   
        $uuid  = substr($str,0,8);   
        $uuid .= substr($str,8,4);   
        $uuid .= substr($str,12,4);   
        $uuid .= substr($str,16,4);   
        $uuid .= substr($str,20,12);   
        return $prefix . $uuid;
    }
}